package org.ying.container;

import cn.hutool.core.text.StrFormatter;

import javax.inject.Named;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

@Named
public class PandaEmbryo {

    /**定义的对象的名称**/
    private String name;
    /**定义的对象的class**/
    private Class pandaClass;
    /**定义的对象的构造器**/
    private Constructor constructor;
    /**定义的对象的所在的配置类class**/
    private Class pandaRoomClass;
    /**定义的对象所在配置类的方法,用以实例化对象**/
    private Method method;
    /**定义的对象的实例化方式,构造器实例化和配置类方法实例化**/
    private EmbryoType embryoType;

    private boolean aspectTarget;

    private boolean proxyTarget;

    public PandaEmbryo(String name, Class pandaClass, Constructor constructor) {
        this.name = name;
        this.pandaClass = pandaClass;
        this.constructor = constructor;
        this.embryoType = EmbryoType.constructor;
    }
    public PandaEmbryo(String name, Class pandaRoomClass, Method method) {
        this.name = name;
        this.pandaRoomClass = pandaRoomClass;
        this.pandaClass = method.getReturnType();
        this.method = method;
        this.embryoType = EmbryoType.method;
    }

    public String getName() {
        return name;
    }

    public Class getPandaClass() {
        return pandaClass;
    }

    public Constructor getConstructor() {
        return constructor;
    }

    public Class getPandaRoomClass() {
        return pandaRoomClass;
    }

    public EmbryoType getEmbryoType() {
        return embryoType;
    }

    public Method getMethod() {
        return method;
    }

    public boolean isAspectTarget() {
        return aspectTarget;
    }

    public void setAspectTarget(boolean aspectTarget) {
        this.aspectTarget = aspectTarget;
    }

    public boolean isProxyTarget() {
        return proxyTarget;
    }

    public void setProxyTarget(boolean proxyTarget) {
        this.proxyTarget = proxyTarget;
    }

    public Object newInstanceByConstructor(Object[] args) {
        if (this.embryoType != EmbryoType.constructor){
            throw new PandaException("should be constructor type");
        }
        try {
            Object o = constructor.newInstance(args);
            return o;
        } catch (Exception e) {
            throw new PandaException(StrFormatter.format("encounter unexpect error when breed panda,name:{},class:{},message:{}"
                    ,name,pandaClass.getName(),e.getMessage()));
        }
    }
    public Object newInstanceByMethod(Object object, Object[] args){
        if (this.embryoType != EmbryoType.method){
            throw new PandaException("should be method type");
        }
        if (object == null){
            throw new PandaException("newInstance for embryoType.method need object that the method is");
        }
        try {
            Object o = method.invoke(object, args);
            return o;
        } catch (Exception e) {
            throw new PandaException(StrFormatter.format("encounter unexpect error when breed panda,name:{},class:{},message:{}"
                    ,name,pandaClass.getName(),e.getMessage()));
        }
    }


    enum EmbryoType {
        constructor,method
    }

}
